package com.tansun.rule.redis.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import com.tansun.rule.redis.RedisService;

@Service("redisService")
public class RedisServiceImpl<T> implements RedisService<T> {
	@Autowired(required = false)
	private RedisTemplate redisTemplate;

	/**
	 * 批量删除对应的value
	 * 
	 * @param keys
	 */
	public void remove(final String... keys) {
		for (String key : keys) {
			remove(key);
		}
	}

	/**
	 * 批量删除key
	 * 
	 * @param pattern
	 */
	public void removePattern(final String pattern) {
		try {
			Set<String> keys = redisTemplate.keys(pattern);
			if (keys.size() > 0)
				redisTemplate.delete(keys);
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}

	}

	/**
	 * 删除对应的value
	 * 
	 * @param key
	 */
	public void remove(final String key) {
		try {
			if (exists(key)) {
				redisTemplate.delete(key);
			}
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * 判断缓存中是否有对应的value
	 * 
	 * @param key
	 * @return
	 */
	public boolean exists(final String key) {
		try {
			return redisTemplate.hasKey(key);
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * 读取缓存
	 * 
	 * @param key
	 * @return
	 */
	public Object get(final String key) {
		try {
			Object result = null;
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			result = operations.get(key);
			return result;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * 写入缓存
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(final String key, Object value) {
		boolean result = false;
		try {
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
		return result;
	}

	/**
	 * 写入缓存
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(final String key, Object value, Long expireTime) {
		boolean result = false;
		try {
			ValueOperations<String, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value.toString());
			redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
		return result;
	}

	/**
	 * @description 简单的往数组里面添加元素
	 * @param key
	 * @param value
	 */
	@Override
	public int lPush(String key, Object value) {
		try {
			ListOperations<String, Object> oper = redisTemplate.opsForList();
			Long v = oper.leftPush(key, value);
			if (v == null) {
				return 0;
			}
			int backValue = v.intValue();
			return backValue;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 批量往数组里面添加元素
	 * @param key
	 * @param list
	 */
	public int lPushAll(String key, List<T> list) {
		try {
			ListOperations<String, Object> oper = redisTemplate.opsForList();
			Long v = oper.leftPushAll(key, list);
			if (v == null) {
				return 0;
			}
			int backValue = v.intValue();
			return backValue;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 对指定下标的数组元素进行替换
	 * @param key
	 * @param offset
	 * @param value
	 */
	@Override
	public void set(String key, int offset, String value) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			oper.set(key, offset, value);
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 对指定下标的数组进行插入数据
	 * @param key
	 * @param value1
	 *            原有值
	 * @param value2
	 *            插入的值
	 */
	@Override
	public void insert(String key, String value1, String value2) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			int backValue = oper.leftPush(key, value1, value2).intValue();
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 获取指定下标的数组元素
	 * @param key
	 * @param offset
	 */
	@Override
	public void getValueByIndex(String key, int offset) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			String value = oper.index(key, offset);
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 获取数组长度
	 * @param key
	 */
	@Override
	public void size(String key) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			int length = oper.size(key).intValue();
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 移除数组匹配到的数据元素
	 * @param key
	 * @param count
	 *            负数：从右往左 整数：从左往右
	 * @param value
	 *            移除的值
	 */
	@Override
	public void remove(String key, long count, String value) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			int backValue = oper.remove(key, count, value).intValue();
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 保留区间内的元素，区间外的全部删除
	 * @param key
	 * @param start
	 *            区间开始
	 * @param end
	 *            区间结束
	 */
	@Override
	public void trim(String key, int start, int end) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			oper.trim(key, start, end);
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 从左到右，删除第一个元素
	 * @param key
	 */
	public String lpop(String key) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			String value = oper.leftPop(key);
			return value;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	public List<String> lpop(String key, int count) {
		try {
			List<String> list = new ArrayList<String>();
			for (int i = 0; i < count; i++) {
				ListOperations<String, String> oper = redisTemplate.opsForList();
				String popVal = oper.leftPop(key);
				if (!StringUtils.isEmpty(popVal))
					list.add(popVal);
			}
			return list;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	public List<List<String>> lpopList(String key, int count) {
		try {
			List<List<String>> list = new ArrayList<List<String>>();
			for (int i = 0; i < count; i++) {
				ListOperations<String, List<String>> oper = redisTemplate.opsForList();
				List<String> popList = oper.leftPop(key);
				if (popList != null)
					list.add(popList);
			}
			return list;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 查询区间范围内的元素
	 * @param key
	 * @param start
	 * @param end
	 */
	public List<String> lrange(String key, int start, int end) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			List<String> list = oper.range(key, start, end);
			return list;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	public List<List<String>> lrangeList(String key, int start, int end) {
		try {
			ListOperations<String, List<String>> oper = redisTemplate.opsForList();
			List<List<String>> list = oper.range(key, start, end);
			return list;
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}

	/**
	 * @description 两个list之间移元素
	 * @param sourceKey
	 *            源
	 * @param destinationKey
	 *            目的地
	 */
	@Override
	public void rightPopAndLeftPush(String sourceKey, String destinationKey) {
		try {
			ListOperations<String, String> oper = redisTemplate.opsForList();
			String v = oper.rightPopAndLeftPush(sourceKey, destinationKey);
		} finally {// 释放连接
			RedisConnectionUtils.unbindConnection(redisTemplate.getConnectionFactory());
		}
	}
}
